﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EstevesRecordersProject
{

    public class Statistics
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="performanceList"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateStop"></param>
        /// <returns></returns>
        private static MyTimeSpan GetWorktime(List<Performance> performanceList, DateTime dateStart, DateTime dateStop)
        {

            Performance previousState = null;
            TimeSpan ts = new TimeSpan(0, 0, 0);
            MyTimeSpan mts = new MyTimeSpan();
            int count = 0;
            mts.count = 0;

            if (performanceList == null)
            {
                mts.TimeSpan = ts;
                mts.Info = "No performance.";
                return mts;
            }

            int i = 0;
            foreach (Performance p in performanceList)
            {
                TimeSpan tsTemp;
                i++;

                //jesli początek
                if (previousState == null)
                {
                    previousState = p;
                    continue;
                }

                if (p.value == 0 && previousState.value == 1)
                {
                    tsTemp = p.date - previousState.date;
                    mts.count++;
                    ts = ts.Add(tsTemp);
                }
                else if (p.value == previousState.value)
                {
                    count++;
                }

                previousState = p;
            }

            mts.TimeSpan = ts;

            if (count != 0)
            {
                mts.Info = " recorder read same value (count : " + count + ") ";
            }

            return mts;    
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="line"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateStop"></param>
        /// <returns></returns>
        public static MyTimeSpan GetWorktime(Line line, DateTime dateStart, DateTime dateStop)
        {
            List<Performance> performanceList = Repository.GetLinePerformanceInTime(line, dateStart, dateStop);
            return GetWorktime(performanceList, dateStart, dateStop);    
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="recorderList"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateStop"></param>
        /// <returns></returns>
        public static MyTimeSpan GetWorktimeGroup(List<Recorder> recorderList, DateTime dateStart, DateTime dateStop)
        {
            MyTimeSpan timeSpan = new MyTimeSpan();
            timeSpan.TimeSpan = new TimeSpan(0, 0, 0);

            foreach (Recorder r in recorderList)
            {
                foreach (Line l in r.Lines)
                {
                    MyTimeSpan ts = Statistics.GetWorktime(l, dateStart, dateStop);
                    timeSpan.TimeSpan = timeSpan.TimeSpan.Add(ts.TimeSpan);
                    timeSpan.count += ts.count;
                    if ( String.IsNullOrEmpty(timeSpan.Info)) timeSpan.Info +=  ts.Info;
                    else timeSpan.Info += "; " + ts.Info;
                }
            }

            return timeSpan;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="recorderList"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateStop"></param>
        /// <returns></returns>
        public static MyTimeSpan GetIdleTimeGroup(List<Recorder> recorderList, DateTime dateStart, DateTime dateStop)
        {
            MyTimeSpan timeSpan = new MyTimeSpan();
            timeSpan.TimeSpan = new TimeSpan(0, 0, 0);

            foreach (Recorder r in recorderList)
            {
                foreach (Line l in r.Lines)
                {
                    MyTimeSpan ts = Statistics.GetIdleTime(l, dateStart, dateStop);
                    timeSpan.TimeSpan = timeSpan.TimeSpan.Add(ts.TimeSpan);
                    timeSpan.count += ts.count;
                    if (String.IsNullOrEmpty(timeSpan.Info)) timeSpan.Info += ts.Info;
                    else timeSpan.Info += "; " + ts.Info;
                }
            }

            return timeSpan;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="recorderList"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateStop"></param>
        /// <returns></returns>
        public static MyTimeSpan GetWorktimeGroupOR(List<Recorder> recorderList, DateTime dateStart, DateTime dateStop)
        {
            List<Performance> performanceList = new List<Performance>();
            List<Performance> performanceList2 = new List<Performance>();

            foreach (Recorder r in recorderList)
            {
                foreach (Line l in r.Lines)
                {
                    performanceList.AddRange( Repository.GetLinePerformanceInTime(l, dateStart, dateStop ) );
                }
            }

            performanceList = performanceList.OrderBy(p => p.date).ToList();

            TimeSpan ts = new TimeSpan(0, 0, 0);
            MyTimeSpan mts = new MyTimeSpan();
            mts.count = 0;

            if (performanceList == null)
            {
                mts.TimeSpan = ts;
                mts.Info = "No performance.";
                return mts;
            }

            

            int pointer = 0;

            foreach (Performance p in performanceList)
            {
                if (p.value == 0 && pointer>0) pointer--;
                else if (p.value == 1) pointer++;

                Performance p2 = new Performance();
                p2.id = p.id;
                p2.date = p.date;
                p2.idLinel = p.idLinel;
                p2.value = pointer;

                performanceList2.Add(p2); 
            }

            
            Performance previousState = null;
            int count = 0;
            mts.count = 0;
            
            int i = 0;
            foreach (Performance p in performanceList2)
            {
                TimeSpan tsTemp;
                i++;

                //jesli początek
                if (previousState == null)
                {
                    previousState = p;
                    continue;
                }

                if (p.value == 0 && previousState.value == 1)
                {
                    tsTemp = p.date - previousState.date;
                    mts.count++;
                    ts = ts.Add(tsTemp);
                    previousState = p;
                }
                else if (p.value == 1 && previousState.value ==0){previousState = p;}
                else if (p.value >= 1 && previousState.value >= 1 && (p.value > previousState.value)) { }
                else if (p.value >= 1 && previousState.value >= 1 && (p.value < previousState.value)) { }
                else if (p.value == 0 && previousState.value == 0){previousState = p;}
                else if (p.value == previousState.value) {  }
                else
                {
                    throw new ApplicationException("Something is wrong ...");
                }

                
            }

            mts.TimeSpan = ts;

            if (count != 0)
            {
                mts.Info = " recorder read same value (count : " + count + ") ";
            }

            return mts;    
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="recorderList"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateStop"></param>
        /// <returns></returns>
        public static MyTimeSpan GetIdleTimeGroupOR(List<Recorder> recorderList, DateTime dateStart, DateTime dateStop)
        { 
            MyTimeSpan ts = GetWorktimeGroupOR( recorderList,  dateStart, dateStop);

            //Get whole performance
            List<Performance> performanceList = new List<Performance>();
            foreach (Recorder r in recorderList)
            {
                foreach (Line l in r.Lines)
                {
                    performanceList.AddRange(Repository.GetLinePerformanceInTime(l, dateStart, dateStop));
                }
            }
            performanceList = performanceList.OrderBy(p => p.date).ToList();

            DateTime firstAction = new DateTime();
            DateTime lastAction = new DateTime();

            //get first action
            foreach (Performance p in performanceList)
            {
                if (p.value == 1)
                {
                    firstAction = p.date;
                    break;
                }
            }

            //get last action
            performanceList = performanceList.OrderByDescending(p => p.date).ToList();
            foreach (Performance p in performanceList)
            {
                if (p.value == 1)
                {
                    lastAction = p.date;
                    break;
                }
            }

            TimeSpan actionTime = lastAction.Subtract(firstAction);

            MyTimeSpan tsNew = ts;
            tsNew.TimeSpan = actionTime - ts.TimeSpan;

            return tsNew;

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="line"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateStop"></param>
        /// <returns></returns>
        public static MyTimeSpan GetIdleTime(Line line, DateTime dateStart, DateTime dateStop)
        {
            List<Performance> performanceList = Repository.GetLinePerformanceInTime(line, dateStart, dateStop);

            Performance previousState = null;
            TimeSpan ts = new TimeSpan(0, 0, 0);
            MyTimeSpan mts = new MyTimeSpan();
            int count = 0;
            mts.count = 0;

            if (performanceList == null)
            {
                mts.TimeSpan = ts;
                mts.Info = "No performance.";
                return mts;
            }

            int i = 0;
            foreach (Performance p in performanceList)
            {
                TimeSpan tsTemp;
                i++;

                //jesli początek
                if (previousState == null)
                {
                    previousState = p;
                    continue;
                }

                


                if (p.value == 1 && previousState.value == 0)
                {
                    tsTemp = p.date - previousState.date;
                    mts.count++;
                    ts = ts.Add(tsTemp);
                }
                else if (p.value == previousState.value)
                {
                    count++;
                }

                previousState = p;

            }

            mts.TimeSpan = ts;

            if (count != 0)
            {
                mts.Info = " recorder read same value (count : " + count + ") ";
            }

            return mts;
        }

        public static MyTimeSpan GetWorktTimeLongerThan(Line line, DateTime dateStart, DateTime dateStop, TimeSpan min)
        {
            List<Performance> performanceList = Repository.GetLinePerformanceInTime(line, dateStart, dateStop);

            Performance previousState = null;
            TimeSpan ts = new TimeSpan(0, 0, 0);
            MyTimeSpan mts = new MyTimeSpan();
            int count = 0;
            mts.count = 0;

            if (performanceList == null)
            {
                mts.TimeSpan = ts;
                mts.Info = "No performance.";
                return mts;
            }

            int i = 0;
            foreach (Performance p in performanceList)
            {
                TimeSpan tsTemp;
                i++;

                //jesli początek
                if (previousState == null)
                {
                    previousState = p;
                    continue;
                }


                if (p.value == 0 && previousState.value == 1)
                {
                    tsTemp = p.date - previousState.date;
                    
                    if (tsTemp >= min)
                    {
                        mts.count ++;
                        ts = ts.Add(tsTemp);
                    }
                }
                else if (p.value == previousState.value)
                {
                    count++;
                }

                previousState = p;

            }

            mts.TimeSpan = ts;

            if (count != 0)
            {
                mts.Info = " recorder read same value (count : " + count + ") ";
            }

            return mts;
        }


        public static MyTimeSpan GetIdleTimeLongerThan(Line line, DateTime dateStart, DateTime dateStop, TimeSpan min)
        {
            List<Performance> performanceList = Repository.GetLinePerformanceInTime(line, dateStart, dateStop);

            Performance previousState = null;
            TimeSpan ts = new TimeSpan(0, 0, 0);
            MyTimeSpan mts = new MyTimeSpan();
            int count = 0;
            mts.count = 0;

            if (performanceList == null)
            {
                mts.TimeSpan = ts;
                mts.Info = "No performance.";
                return mts;
            }

            int i = 0;
            foreach (Performance p in performanceList)
            {
                TimeSpan tsTemp;
                i++;

                //jesli początek
                if (previousState == null)
                {
                    previousState = p;
                    continue;
                }


                if (p.value == 1 && previousState.value == 0)
                {
                    tsTemp = p.date - previousState.date;

                    if (tsTemp >= min)
                    {
                        mts.count++;
                        ts = ts.Add(tsTemp);
                    }
                }
                else if (p.value == previousState.value)
                {
                    count++;
                }

                previousState = p;

            }

            mts.TimeSpan = ts;

            if (count != 0)
            {
                mts.Info = " recorder read same value (count : " + count + ") ";
            }

            return mts;
        }
    }
}
